home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_400 / 425_01 / tar / extract.c < prev    next >
Text File  |  1994-04-02  |  14KB  |  485 lines

  1. /* extarct.c - extract files from (tape) archive.
  2.  * This is a part of the Tar program (see file tar.c)
  3.  * Author: T.V.Shaporev
  4.  * Creation date: 14 Dec 1990
  5.  */
  6. #include <stdio.h>
  7.  
  8. #include "sysup.h"
  9. #include "nodedef.h"
  10. #include "modern.h"
  11. #ifdef MODERN
  12. #    include <string.h>
  13. #else
  14.     char *strncpy();
  15.     int  strlen();
  16. #endif
  17. #ifndef MSDOS
  18.     int  mknod(), chown(), utime();
  19.     long time();
  20. #endif
  21.  
  22. #include "zippipe.h"
  23. #include "lzwbits.h"
  24. #include "lzwhead.h"
  25. #include "compress.h"
  26. #include "define.h"
  27. #include "lzpack.h"
  28.  
  29. static int soctus   __ARGS__(( register char *, register short* ));
  30.        int soctul   __ARGS__(( register char *, register long * ));
  31. static int mismatch __ARGS__(( register char *, register char *, int ));
  32.  
  33. #define octal(c) (((c)&0370)=='0')
  34.  
  35. static char unknown[] = "Tar: \'%s\' unknown file type \'%c\'\n";
  36. #define _unknown (unknown+9)
  37.  
  38. static int soctus(s, u)
  39. register short *u;
  40. register char *s;
  41. {
  42.    register i;
  43.    while (*s == ' ') ++s;
  44.    for (*u=0, i=0; octal(*s) && i<7; i++, s++) *u = (*u<<3)|(*s&7);
  45.    return *s!=' ' && *s!='\0';
  46. }
  47.  
  48. int soctul(s, u)
  49. register long *u;
  50. register char *s;
  51. {
  52.    register i;
  53.    while (*s == ' ') ++s;
  54.    for (*u=0, i=0; octal(*s) && i<11; i++, s++) *u = (*u<<3)|(*s&7);
  55.    return *s!=' ' && *s!='\0';
  56. }
  57.  
  58. int gethead()
  59. {
  60.    short n;
  61.    static short errcount = 0;
  62.    register char *err_text = "Tar: bad directory structure\n";
  63.  
  64.    if ((hblock = readtape()) == NULL) return ERROR;
  65.    if ((hblock->name[0]) == '\0') {
  66.       return errcount ? (++errcount, ERROR) : FALSE;
  67.    }
  68.    if (soctus(hblock->chksum, &n)) goto bad;
  69.    if (n != headsum(hblock)) {
  70.       err_text = "Tar: directory checksum error\n"; goto bad;
  71.    }
  72.    if (soctus(hblock->mode,  (short*)&(st.st_mode)) ||
  73.        soctus(hblock->uid,   (short*)&(st.st_uid))  ||
  74.        soctus(hblock->gid,   (short*)&(st.st_gid))  ||
  75.        soctul(hblock->size,  (long *)&(st.st_size)) ||
  76.        soctul(hblock->mtime, (long *)&(st.st_mtime))) goto bad;
  77.    if (hblock->filetype == TF_CHR || hblock->filetype == TF_BLK) {
  78.       if (soctus(hblock->x.new.devmajor, &dmajor) ||
  79.           soctus(hblock->x.new.devminor, &dminor)) goto bad;
  80.    }
  81.    if (errcount != 0) {
  82.       (void)fprintf(myout,
  83.                     "Tar: %d blocks skipped to find header\n", errcount);
  84.       errcount = 0;
  85.    }
  86.    if (hblock->filetype == TF_OLD || hblock->filetype == TF_REG) {
  87.       (void)soctul(hblock->x.old.srclen, &codesize); /* no sence for    */
  88.       (void)soctul(hblock->x.old.srcsum, &longcsum); /* non-packed file */
  89.    } else {
  90.       longcsum = codesize = 0;
  91.    }
  92.    return TRUE;
  93. bad:
  94.    if (errcount++ == 0) (void)fprintf(myout, err_text);
  95.    if (!i_flag) done(ERREAD);
  96.    return ERROR;
  97. }
  98.  
  99. static int tstfield __ARGS__(( char *, int ));
  100.  
  101. static int tstfield(s,n) /* is the field a valid octal number? */
  102. char *s; int n;
  103. {
  104.    register j;
  105.  
  106.    for (j=0; j<n && octal(s[j]); j++);
  107.    if (!j || j >= n) return FALSE;
  108.    if (s[j] == ' ') ++j;
  109.    while (j<n && !s[j++]);
  110.    return j>=n;
  111. }
  112.  
  113. #define TstField(x) tstfield(x, sizeof(x))
  114.  
  115. short isextent(allx, allb)
  116. short *allx; long *allb;
  117. {
  118.    short n;
  119.  
  120.    if ((hblock->filetype != TF_OLD && hblock->filetype != TF_REG) ||
  121.        !TstField(hblock->x.s_v.extent) ||
  122.        !TstField(hblock->x.s_v.allext) ||
  123.        !TstField(hblock->x.s_v.total)) return ERROR;
  124.    (void)soctus(hblock->x.s_v.extent, &n);
  125.    (void)soctus(hblock->x.s_v.allext, allx);
  126.    (void)soctul(hblock->x.s_v.total,  allb);
  127.    return n < 1 || n > *allx || *allb <= st.st_size ? ERROR : n;
  128. }
  129.  
  130. int ismagic()
  131. {
  132.    register i;
  133.    register char *p, *q;
  134.    static char magic_list[][8] = { TMAGIC, GMAGIC };
  135.  
  136.    if (hblock->filetype != TF_OLD) {
  137.       for (i=0; i<dimof(magic_list); i++) {
  138.          p = magic_list[i];
  139.          q = hblock->x.new.magic;
  140.          while (*q && *q == *p) {
  141.             ++q; p++;
  142.          }
  143.          if (*q == '\0' && (*p == '\0' || *p == ' '))
  144.             return magic_list[i][0];
  145.       }
  146.    }
  147.    return 0;
  148. }
  149.  
  150. char prefix()
  151. {
  152.    switch (hblock->filetype) {
  153.       case TF_CTG: /* ??? contiguous file */
  154.       case TF_OLD:
  155.       case TF_REG:
  156.       case TF_LNK: return ' ';
  157.       case TF_SYM: return 'l';
  158.       case TF_CHR: return 'c';
  159.       case TF_BLK: return 'b';
  160.       case TF_DIR: return 'd';
  161.       case TF_QUE: return 'p';
  162.       case GF_DMP: return 'D';
  163.       case GF_MUL: return ',';
  164.       case GF_VOL: return 'v';
  165.    }
  166.    return '?';
  167. }
  168.  
  169. int usize() /* is it valid to use file size in header */
  170. {
  171.    switch (hblock->filetype) {
  172.       case TF_OLD: case TF_REG: case TF_CTG:
  173.       case GF_DMP: case GF_MUL: case GF_SPR: /* what's it? I wonder */
  174.          return TRUE;
  175.    }
  176.    return FALSE;
  177. }
  178.  
  179. void skipfile()
  180. {
  181.    register long blocks;
  182.  
  183.    for (blocks=(st.st_size+BLKSIZE-1)/BLKSIZE; blocks>0; blocks--) {
  184.       if (readtape() == NULL) {
  185.          (void)fprintf(myout, "Tar: tape read error\n");
  186.          if (i_flag) done(ERREAD);
  187.          return;
  188.       }
  189.    }
  190. }
  191.  
  192. static int mismatch(p, s, l)
  193. register char *p, *s; int l;
  194. {
  195.    register i;
  196.  
  197.    for (i=0; *p && i<l; ++p, i++) {
  198.       if (*p == '*') {
  199.          while (*++p == '*') ;
  200.  
  201.          while (l>=i) {
  202.             if (!mismatch(p, s+i, l-i)) return FALSE;
  203.             ++i;
  204.          }
  205.          return TRUE;
  206.       } else if (*p != '?') {
  207.          if (s[i] != *p) return ERROR;
  208.       }
  209.    }
  210.    return *p || i<l;
  211. }
  212.  
  213. int inargs(argc, argv, n)
  214. int argc; register char *argv[], *n;
  215. {
  216.    register i; register j; register k;
  217.    register char *p;
  218.  
  219.    for (i=0; i<argc; i++) {
  220.       if (s_flag) {
  221.          for (p=argv[i], j=0; j<MAXTNAME && p[j]==n[j] && p[j]!=0; j++);
  222.          if (j<MAXTNAME && p[j]==0 && (n[j]==0 || n[j]=='/')) return TRUE;
  223.       } else {
  224.          j = 0;
  225.          while (j<MAXTNAME && n[j]) {
  226.             do ++j; while (n[j]!='/' && n[j]!=0);
  227.             k = mismatch(argv[i], n, j);
  228.             if (k == ERROR) goto extloop;
  229.             if (k == FALSE) return TRUE;
  230.          }
  231.       }
  232.       extloop:;
  233.    }
  234.    return FALSE;
  235. }
  236.  
  237. void scantape(argc, argv, handler)
  238. int argc; char *argv[]; void (*handler)__ARGS__((void));
  239. {
  240.    register k;
  241.  
  242.    while ((k=gethead()) != FALSE) {
  243.       if (k == ERROR) continue;
  244.       if (argc < 1 || inargs(argc, argv, hblock->name)) {
  245.          (*handler)();
  246.       } else {
  247.          if (usize()) skipfile();
  248.       }
  249.    }
  250.    if (pktype == PKZIP) {
  251.       while ((k=unzread((char*)hblock, BLKSIZE)) == BLKSIZE);
  252.       if (k != ERROR) {
  253.          if (k) (void)fprintf(myout, "Tar: final block misaligned\n");
  254.          k = unzclose();
  255.       }
  256.       if (k) {
  257.          register char *p = NULL;
  258.          if (k == -1) p = "error"; else if (v_flag) p = "warning";
  259.          if (p) (void)fprintf(myout, "Tar: unzip %s: %s\n",
  260.                                      p, ziperrlist[ziperror]);
  261.       }
  262.    }
  263. }
  264.  
  265. extern long thisread;
  266. extern int arcget __ARGS__(( void ));
  267.  
  268. void catalog()
  269. {
  270.    register long thislen;
  271.    register reverse = FALSE, skipped = FALSE;
  272.    register char *p;
  273.    static no_mem = FALSE;
  274.    short nx = 1, allx; long xinfo;
  275.    extern char ofname[];
  276.    register c;
  277.  
  278.    p = hblock->name;
  279.    c = hblock->filetype;
  280.  
  281.    if (v_flag) prmode(prefix(), (int)(st.st_mode));
  282.    if ((c == TF_OLD || c == TF_REG) && (nx=isextent(&allx, &xinfo)) < 1) {
  283.       if (st.st_size <= codesize) {
  284.          reverse = TRUE;
  285.       } else if (pktype == PKfLZW) {
  286.          register i, j;
  287.  
  288.          i = strlen(hblock->name);
  289.          if (hblock->name[--i] == 'Z' && hblock->name[--i] == '.') {
  290.             p = strncpy(ofname, hblock->name, MAXTNAME);
  291.             (void)z_getmem(BITS);
  292.             codesize = 0; thisread = 0;
  293.             if ((j = dbegin(arcget)) == 0) {
  294.                do {
  295.                   if ((j = dpiece(pk_out, pksize)) > 0) codesize += j;
  296.                } while (j == pksize);
  297.                skipped = TRUE;
  298.             } else if (j > 0) {
  299.                bacouple(); /* file is not in compressed format */
  300.             } else if (!no_mem) {
  301.                (void)fprintf(myout, "